package com.learn.io.bio.bothway.persistent.common;

import com.learn.constant.CommonConstant;
import com.learn.constant.MathConstant;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Socket持续通信:服务器
 *
 * 线程复用，创建线程耗时，回收线程慢
 * 防止短时间内高并发，指定线程池大小，超过数量将等待，方式短时间创建大量线程导致资源耗尽，服务挂掉
 */
public class SocketServer {

    static String message = "Hello Client,I get the message.";

    public static void main(String[] args) throws Exception {
        // 监听指定的端口
        int port = CommonConstant.SOCKET_SERVER_PORT;
        ServerSocket server = new ServerSocket(port);

        // server将一直等待连接的到来
        System.out.println("server将一直等待连接的到来");

        //如果使用多线程，那就需要线程池，防止并发过高时创建过多线程耗尽资源
        ExecutorService threadPool = Executors.newFixedThreadPool(MathConstant.INT_100);

        while(true){
            Socket socket = server.accept();

            Runnable runnable=()->{
                try {
                    // 建立好连接后，从socket中获取输入流，并建立缓冲区进行读取
                    InputStream inputStream = socket.getInputStream();
                    byte[] bytes = new byte[MathConstant.INT_1024];
                    int len;
                    StringBuilder sb = new StringBuilder();
                    while ((len = inputStream.read(bytes)) != MathConstant.INT_MINUS_ONE) {
                        // 注意指定编码格式，发送方和接收方一定要统一，建议使用UTF-8
                        sb.append(new String(bytes, MathConstant.INT_ZERO, len, CommonConstant.DEFAULT_CHARSET_NAME));
                    }
                    System.out.println("get message from client: " + sb);

                    // 返回消息
                    OutputStream outputStream = socket.getOutputStream();
                    outputStream.write(message.getBytes(CommonConstant.DEFAULT_CHARSET_NAME));

                    inputStream.close();
                    outputStream.close();
                    socket.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
            threadPool.submit(runnable);
        }
    }
}
